package com.taiji.dianthus.service.sys.impl;

import com.taiji.dianthus.common.BusinessMessage;
import com.taiji.dianthus.dao.sys.SysLogRepository;
import com.taiji.dianthus.domain.sys.DSysUser;
import com.taiji.dianthus.domain.sys.LogExcel;
import com.taiji.dianthus.domain.sys.SysLog;
import com.taiji.dianthus.service.sys.RoleUserService;
import com.taiji.dianthus.service.sys.SysLogService;
import com.taiji.dianthus.service.sys.UserService;
import com.taiji.dianthus.util.DateUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static com.taiji.dianthus.util.DateUtil.DATE_PATTERN;

/**
 * @ClassName SysLogServiceImpl
 * @Description
 * @Author H.M
 * @Date 2020/6/22
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SysLogServiceImpl implements SysLogService {

    @Autowired
    private SysLogRepository repository;

    @Autowired
    private UserService userService;

    @Autowired
    private RoleUserService roleUserService;

    @Value("${safty_role}")
    private String saftyRole;//安全管理员
    @Value("${system_role}")
    private String systemRole;//系统管理员
    @Value("${audit_role}")
    private String auditRole;//审计管理员
    @Value("${user_role}")
    private String userRole;//普通用户

    /**
     * 保存日志方法
     *
     * @param user
     * @param operation
     * @param ipAddress
     * @param desc
     * @param result
     * @param remark
     */
    @Override
    public SysLog save(DSysUser user, Integer operation, String ipAddress,
                       String desc, Integer result, String remark) {
        SysLog sysLog = new SysLog();
        sysLog.setUserId(user.getId());
        String roleId = roleUserService.getRoleIdByUserCode(user.getId());
        sysLog.setRoleId(roleId);
        sysLog.setUserName(user.getName());
        sysLog.setLoginName(user.getUserLoginName());
        sysLog.setOperation(operation);
        sysLog.setIpAddress(ipAddress);
        sysLog.setOperationDesc(desc);
        sysLog.setOperationResult(result);
        sysLog.setOperationRemark(remark);
        return repository.save(sysLog);
    }

    /**
     * 查询日志列表
     *
     * @param pageSize
     * @param currentPage
     * @param operation
     * @param startDate
     * @param endDate
     * @param userName
     * @param operationDesc
     * @return
     */
    @Override
    public BusinessMessage list(Integer pageSize, Integer currentPage, String userName, Integer operation,
                                String operationDesc, Integer result, String startDate, String endDate, DSysUser currentUser) {
        BusinessMessage message = new BusinessMessage();
        try {
            String roleId = roleUserService.getRoleIdByUserCode(currentUser.getId());
            Sort sort = new Sort(Sort.Direction.DESC, "createTime");
            //分页参数
            Pageable pageable = PageRequest.of(currentPage, pageSize, sort);
            Page<SysLog> logPage;
            //创建查询参数
            Specification<SysLog> spec = (Root<SysLog> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
                List<Predicate> pl = new ArrayList<Predicate>();
                if (!StringUtils.isEmpty(userName)) {
                    pl.add(cb.like(root.<String>get("userName"), "%" + userName + "%"));
                }
                if (!StringUtils.isEmpty(operationDesc)) {
                    pl.add(cb.like(root.<String>get("operationDesc"), "%" + operationDesc + "%"));
                }
                if (null != operation && operation != 0) {
                    pl.add(cb.equal(root.<String>get("operation"), operation));
                }

                if (null != result) {
                    pl.add(cb.equal(root.<String>get("operationResult"), result));
                }
                //开始时间
                if (!StringUtils.isEmpty(startDate)) {
                    Date start = DateUtil.stringToDate(startDate, DATE_PATTERN);
                    pl.add(cb.greaterThanOrEqualTo(root.<Date>get("createTime"), start));
                }

                //结束时间
                if (!StringUtils.isEmpty(endDate)) {
                    Date end = DateUtil.stringToDate(endDate, DATE_PATTERN);
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(end);
                    calendar.add(Calendar.DATE, 1);
                    pl.add(cb.lessThan(root.<Date>get("createTime"), calendar.getTime()));
                }
                if (!StringUtils.isEmpty(roleId) && !"".equals(roleId) && roleId.equals(saftyRole)) {//安全管理员
                    Predicate pred1 = cb.equal(root.get("roleId"), auditRole);
                    Predicate pred2 = cb.equal(root.get("roleId"), userRole);
                    pl.add(cb.or(pred1, pred2));
                }
                if (!StringUtils.isEmpty(roleId) && !"".equals(roleId) && roleId.equals(auditRole)) {//审计管理员
                    Predicate pred1 = cb.equal(root.get("roleId"), saftyRole);
                    Predicate pred2 = cb.equal(root.get("roleId"), systemRole);
                    pl.add(cb.or(pred1, pred2));
                }

                //查询未删除的
                pl.add(cb.equal(root.<Integer>get("enableFlag"), 1));
                return cb.and(pl.toArray(new Predicate[0]));
            };
            logPage = repository.findAll(spec, pageable);
            message.setMsg("查询日志列表成功");
            message.setData(logPage);
            message.setSuccess(true);
        } catch (Exception e) {
            e.printStackTrace();
            message.setMsg("查询日志列表失败");
        } finally {
            return message;
        }

    }

    /**
     * 查询该天的登录人数
     *
     * @param dayStr
     * @return
     */
    @Override
    public Integer countLoginByDay(String dayStr) {
        Date date = DateUtil.stringToDate(dayStr, "yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        //当前日期零点
        Date startDate = calendar.getTime();
        calendar.add(Calendar.DATE, 1);
        //当前日期的后一天零点
        Date endDate = calendar.getTime();
        Integer count = repository.countByDate(startDate, endDate);
        return count;
    }

    /**
     * 查询该月的登录人数
     *
     * @param monthStr
     * @return
     */
    @Override
    public Integer countLoginByMonth(String monthStr) {
        Date date = DateUtil.stringToDate(monthStr, "yyyy-MM");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        //该月第一天
        Date startDate = calendar.getTime();
        //下个月的第一天零点
        calendar.set(Calendar.MONTH, month + 1);
        Date endDate = calendar.getTime();
        Integer count = repository.countByDate(startDate, endDate);
        return count;
    }

    @Override
    public List<LogExcel> listNoPage(String userName, Integer operation, String operationDesc, Integer result, String startDate, String endDate, DSysUser currentUser) {
        //创建查询参数
        List<LogExcel> logExcelArrayList = new ArrayList<>();
        try {
            Sort sort = new Sort(Sort.Direction.DESC, "createTime");
            String roleId = roleUserService.getRoleIdByUserCode(currentUser.getId());
            Specification<SysLog> spec = (Root<SysLog> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
                List<Predicate> pl = new ArrayList<Predicate>();
                if (!StringUtils.isEmpty(userName)) {
                    pl.add(cb.like(root.<String>get("userName"), "%" + userName + "%"));
                }
                if (!StringUtils.isEmpty(operationDesc)) {
                    pl.add(cb.like(root.<String>get("operationDesc"), "%" + operationDesc + "%"));
                }
                if (null != operation && operation != 0) {
                    pl.add(cb.equal(root.<String>get("operation"), operation));
                }

                if (null != result) {
                    pl.add(cb.equal(root.<String>get("operationResult"), result));
                }
                //开始时间
                if (!StringUtils.isEmpty(startDate)) {
                    Date start = DateUtil.stringToDate(startDate, DATE_PATTERN);
                    pl.add(cb.greaterThanOrEqualTo(root.<Date>get("createTime"), start));
                }

                //结束时间
                if (!StringUtils.isEmpty(endDate)) {
                    Date end = DateUtil.stringToDate(endDate, DATE_PATTERN);
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(end);
                    calendar.add(Calendar.DATE, 1);
                    pl.add(cb.lessThan(root.<Date>get("createTime"), calendar.getTime()));
                }
                if (!StringUtils.isEmpty(roleId) && !"".equals(roleId) && roleId.equals(saftyRole)) {//安全管理员
                    Predicate pred1 = cb.equal(root.get("roleId"), auditRole);
                    Predicate pred2 = cb.equal(root.get("roleId"), userRole);
                    pl.add(cb.or(pred1, pred2));
                }
                if (!StringUtils.isEmpty(roleId) && !"".equals(roleId) && roleId.equals(auditRole)) {//审计管理员
                    Predicate pred1 = cb.equal(root.get("roleId"), saftyRole);
                    Predicate pred2 = cb.equal(root.get("roleId"), systemRole);
                    pl.add(cb.or(pred1, pred2));
                }

                //查询未删除的
                pl.add(cb.equal(root.<Integer>get("enableFlag"), 1));
                return cb.and(pl.toArray(new Predicate[0]));
            };
            List<SysLog> logs = repository.findAll(spec, sort);

            if (CollectionUtils.isNotEmpty(logs)) {
                logExcelArrayList = logs.stream().map(dict -> {
                    LogExcel dto = new LogExcel();
                    dto.setCreateTime(dict.getCreateTime());
                    dto.setIpAddress(dict.getIpAddress());
                    //1 登陆 2 save 3 update 4 delete 5 select
                    dto.setOperationStr(dict.getOperation() == 1 ? "登陆" : dict.getOperation() == 2 ? "保存" : dict.getOperation() == 3 ? "更新" : dict.getOperation() == 4 ? "删除" : dict.getOperation() == 5 ? "查询" : "");
                    dto.setOperationDesc(dict.getOperationDesc());
                    dto.setOperationRemark(dict.getOperationRemark());
                    dto.setOperationResultStr(dict.getOperationResult() == 1 ? "成功" : "失败");
                    dto.setLoginName(dict.getLoginName());
                    dto.setUserName(dict.getUserName());
                    return dto;
                }).collect(Collectors.toList());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return logExcelArrayList;
    }
}
